#include "./string.h"


char *mds_string_create( size_t len )
{
	const size_t bytes  = len+1;
	const size_t total  = bytes+ sizeof(size_t);
	char        *array  = MDS_CALLOC_AS(char, total );
	if( !array ) return NULL;
	
	*(size_t *)array = len;
	return &array[sizeof(size_t)];
}

size_t mds_string_length( const char *str )
{
	if( str )
	{
		str -= sizeof(size_t);
		return *(size_t *)str;
	}
	else 
	{
		return 0;
	}
	
}

void mds_string_delete( char *str )
{
	if( str )
	{
		size_t total = sizeof(size_t);
		assert( str );
		str -= sizeof(size_t);
		total += (*(size_t *)str);
		++total;
		MDS_FREE_AS(char, str, total );
	}
}

char *mds_string_copy( const char *s )
{
	const size_t len = s ? strlen(s) : 0;
	char *       ans = mds_string_create( len );
	memcpy( ans, s, len );
	return ans;
}

#include <stdarg.h>

char    *mds_string( const char *fmt, ... )
{
	assert( fmt != NULL );
	int length  = 16;
	for(;;)
	{
		char *buffer = MDS_CALLOC_AS(char,length);
		if( !buffer )
			return NULL;
		
		va_list ap;
		va_start( ap, fmt );
		{
			const int  result  = vsnprintf( buffer, length, (void*)fmt, ap);
			const int  success = (result >= 0 && result < length); /* WIN32 and GLIBC compatible */
			va_end (ap);
			if( success )
			{
				char *ans = mds_string_copy( buffer );
				MDS_FREE_AS(char,buffer,length);
				return ans;
			}
			MDS_FREE_AS(char,buffer,length);
			length <<= 1;
		}
		
	}
	
}

/* strtok_r */
char * mds_strtok_r(char *s, const char *delimiters, char **lasts)
{
	char *sbegin, *send;
	sbegin = s ? s : *lasts;
	sbegin += strspn(sbegin, delimiters);
	if (*sbegin == '\0') 
	{
		*lasts = "";
		return NULL;
	}
	send = sbegin + strcspn(sbegin, delimiters);
	if (*send  != '\0')
		*send++ = '\0';
	*lasts = send;
	return sbegin;
}


char * mds_string_read( const char *filename )
{
	FILE  *fp = NULL;
	long   nb = 0;
	char  *data = NULL;
	
	/** open the file **/
	if( NULL == ( fp = fopen( filename, "rb" ) ) )
	{
		return NULL;
	}
	
	/** find its length **/
	if( ( nb = mds_file_length(fp) ) < 0 )
	{
		fclose( fp ); return NULL;
	}
	
	/** prepare memory **/
	if( NULL == ( data = mds_string_create(nb+1) ) )
	{
		fclose( fp ); return NULL;
	}
	
	/** load file content **/
	if( 1 != fread( data, nb, 1, fp) )
	{
		mds_string_delete( data );
		fclose( fp );
		return NULL;
	}
	
	assert( fp   );
	assert( data );
	data[nb] = 0;
	fclose( fp );
	return data;
}

